package com.klangner.go.app.strategy;

import java.util.Comparator;

import com.klangner.go.app.rules.BoardModel;
import com.klangner.go.app.rules.GoConstants;
import com.klangner.go.model.IBoard;


public abstract class BasicGoEstimator implements IGoEstimator{

    static class EstimatedGoPosition {
        EstimatedGoPosition( BoardModel position, float value, int color ) {
            position_ = position;
            value_ = value;
            color_ = color;

            num_entries_ = 1;
        }

        public String toString() {
            return position_ + " value = " + value_ + ", color = " + color_;
        }

        BoardModel position_;
        float value_;
        int color_; // from who's point of view was the estimation made

        int num_entries_; // how many times this appeared during estimation
    }

    static class NumEntriesComparator implements Comparator {
        public int compare( Object left, Object right ) {
            EstimatedGoPosition leftPos = (EstimatedGoPosition)left;
            EstimatedGoPosition rightPos = (EstimatedGoPosition)right;

            if (leftPos.num_entries_ < rightPos.num_entries_ )
                return -1;
            else if (leftPos.num_entries_== rightPos.num_entries_ )
                return 0;
            else
                return 1;
        }
    }


// GoEstimatorInterface method implementation
        // this returns an estimation of the position's value, from
        // the point of view of the "color" player
    public float estimatePosition(BoardModel position, int color) {
        int gameState = checkPositionState(position);

            // the game is still in progress
        if (gameState == GoConstants.InProgress) {

/*
                // First look for the position in the estimation history.
            boolean found = false;

            for (Iterator it = estimationHistory_.iterator();
                 it.hasNext();) {
                EstimatedGoPosition estimatedPosition =
                    (EstimatedGoPosition)(it.next());
                if ( position.sameAs( estimatedPosition.position_) ) {
                    found = true;

                    Debug.assert( color != GoConstants.EMPTY,
                                  "Bad color in estimatePosition" );
                    float value = estimatedPosition.value_;
                    if ( estimatedPosition.color_ != color ) {

//  Debug.log( "Matches the opposite color. Estimation for " + color + " is " + value + " in " + position + ", we'll use " + (-value));

                        value = - value;
                    }

//                     Debug.log( "Estimation cache: " + estimationHistory_ );
//                     Debug.log("Match " + estimatedPosition.num_entries_ +
//                               "times in estimation history: " + position);


                    estimatedPosition.num_entries_++;
                    Debug.log( "Estimation cache size = " + estimationHistory_.size() + " positions." );

                    return value;
                }
            }
*/

            float result = heuristicPositionEstimation(position, color);
            nrVariations_++;

//            System.out.println("Estimated variations = " + nrVariations_);
//            System.out.println("Estimation cache size = " + estimationHistory_.size());

/*
            if (!found) {
                estimationHistory_.add( new EstimatedGoPosition(
                                            position, result, color ) );
            }
*/
            return result;
        }

            // the game is over
        else {
            float result = gameResultValue(gameState, color);
            return result;
        }
    }

        // returns a heuristic evaluation of the <position> from the point of view
        // of the <color> player
    protected abstract float heuristicPositionEstimation(BoardModel position,
                                                         int color);

        // returns the value of a final position, depending on the result
        // and "our" color
    protected float gameResultValue(int gameState, int color) {
        switch (gameState) {
            case GoConstants.BlackWIN:
                if (color == IBoard.BLACK_STONE)
                    return GoStrategyConstants.VictoryValue;
                else
                    return GoStrategyConstants.LossValue;
            case GoConstants.WhiteWIN:
                if (color == IBoard.BLACK_STONE)
                    return GoStrategyConstants.LossValue;
                else
                    return GoStrategyConstants.VictoryValue;
            case GoConstants.JIGO:
                return GoStrategyConstants.JigoValue;
            default:
                return GoStrategyConstants.UndefinedValue;
        }
    }
        // A vector of EstimatedGoPosition
//    List estimationHistory_ = new PriorityQueue( 10, new NumEntriesComparator() );

    private int nrVariations_ = 0;
}
